package com.rran.study.designpattern.factory.singleton.lazy;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @author yy
 * @Type DclLazySingleton.java
 * @Desc DCL版本
 * @date 2020/7/23 10:10
 */
public class DCLLazySingleton {

    //加上volatile防止指令重排序
    private static volatile DCLLazySingleton instance;

    //原来虽然我们把构造方法私有化之后，通过 constructor.setAccessible(true);
    // 是禁止 Java 语言访问检查，也就是不管是不是 private 都可以访问到，
    // 这就导致了调用到了 private 修饰的构造方法，然后出现了第二个实例。
    private DCLLazySingleton() {
    }

    public static DCLLazySingleton getInstance() {
        //是确保字段是在已经初始化的情况下，只读一次。这个局部变量的版本比没有局部变量的版本快 25%。
        DCLLazySingleton result = instance;
        if (result == null) {
            //如果实例是空的，就加锁
            synchronized (DCLLazySingleton.class) {
                //如果实例还是空的，就new一个，然后返回；
                result = instance;
                if (result == null) {
                    instance = result = new DCLLazySingleton();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        DCLLazySingleton instance = DCLLazySingleton.getInstance();
        DCLLazySingleton instance1 = DCLLazySingleton.getInstance();
        System.out.println("instance hashcode:"+instance.hashCode());
        System.out.println("instance1 hashcode:"+instance1.hashCode());
        Constructor<DCLLazySingleton> constructor = DCLLazySingleton.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        DCLLazySingleton reflectInstance = constructor.newInstance();
        System.out.println("reflectInstance hashcode:"+reflectInstance.hashCode());
    }
}
